/*
+-----------------------------------------------------------------------+
| Copyright (c) 2006-2007 Josh Hundley, Mika Tuupola, Dylan Verheul     |
| All rights reserved.                                                  |
|                                                                       |
| Redistribution and use in source and binary forms, with or without    |
| modification, are permitted provided that the following conditions    |
| are met:                                                              |
|                                                                       |
| o Redistributions of source code must retain the above copyright      |
|   notice, this list of conditions and the following disclaimer.       |
| o Redistributions in binary form must reproduce the above copyright   |
|   notice, this list of conditions and the following disclaimer in the |
|   documentation and/or other materials provided with the distribution.|
|                                                                       |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
|                                                                       |
+-----------------------------------------------------------------------+
*/

/* $Id: jquery.teditable.js,v 0.5 2007/01/29 23:03:21 hundleyj Exp $ */

/**
  * jQuery inplace table editor plugin (version 0.5)  
  *
  * Based on jeditable Mika Tuupola and editable by Dylan Verheul <dylan@dyve.net>
  * http://www.appelsiini.net/~tuupola/javascript/jEditable/
  * http://www.dyve.net/jquery/?editable
  *
  * @name  tEditable
  * @type  jQuery
  * @param String  url                POST URL to send edited content
  * @param Hash    options            additional options 
  * @param String  options[name]      POST parameter name of edited content
  * @param String  options[id]        POST parameter name of edited div id
  * @param String  options[rowID]     POST parameter name of edited row
  * @param String  options[colID]     POST parameter name of edited col
  * @param String  options[type]      text or textarea
  * @param Integer options[rows]      number of rows if using textarea
  * @param Integer options[cols]      number of columns if using textarea
  * @param Mixed   options[height]    'auto' or height in pixels
  * @param Mixed   options[width]     'auto' or width in pixels 
  * @param String  options[postload]  POST URL to fetch content before editing
  * @param String  options[getload]   GET URL to fetch content before editing
  * @param String  options[data]      Or content given as paramameter.
  * @param String  options[indicator] indicator html to show when saving
  * @param String  options[tooltip]   optional tooltip text via title attribute
  * @param String  options[event]     jQuery event such as 'click' of 'dblclick'
  * @param String  options[onblur]    'cancel', 'submit' or 'ignore'
  * @param String  options[submit]    submit button value, empty means no button
  * @param String  options[cancel]    cancel button value, empty means no button
  *             
  */

jQuery.fn.tEditable = function(url, options) {
	 var settings = {
        url    : url,
        name   : 'value',
        id     : 'id',
        type   : 'textarea',
        rowID  : 'row',
        colID  : 'col',
        width  : 'auto',
        height : 'auto',
        event  : 'click',
        onblur : 'cancel',
        submit : 'OK',
        indicator : ''
    };
	
	if(options) {
        jQuery.extend(settings, options);
    };
	
	var j = jQuery;
	tbody = j(this).children('tbody');      // get table body
	rows = j(tbody).children('tr');         // get rows	
	cols = j(rows).children('td,th');       // get cols
	
	var numcols = cols.length/rows.length;  // get column count
	j(cols).each(function(i) {		
		var row = parseInt(i/numcols);
		var col = parseInt(i%numcols);
	
		j(this)[settings.event](function() {;
			/* save this to self because this changes when scope changes */
	        var self = this;
	
	        /* prevent throwing an exeption if edit field is clicked again */
	        if (self.editing) {
	            return;
	        }
	
	        /* figure out how wide and tall we are */
	        var width = 
	            ('auto' == settings.width)  ? jQuery(self).css('width')  : settings.width;
	        var height = 
	            ('auto' == settings.height) ? jQuery(self).css('height') : settings.height;
	
	        self.editing    = true;
	        self.revert     = jQuery(self).html();
	        self.innerHTML  = '';
	
	        /* create the form object */
	        var f = document.createElement('form');
	
	        /*  main input element */
	        var i;
	        switch (settings.type) {
	            case 'textarea':
	                i = document.createElement('textarea');
	                if (settings.rows) {
	                    i.rows = settings.rows;
	                } else {
	                    jQuery(i).css('height', height);
	                }
	                if (settings.cols) {
	                    i.cols = settings.cols;
	                } else {
	                    jQuery(i).css('width', width);
	                }  	
	                break;
	            case 'select':
	                i = document.createElement('select');
	                break;
	            default:
	                i = document.createElement('input');
	                i.type  = settings.type;
	                jQuery(i).css('width', width);
	                jQuery(i).css('height', height);
	                /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
	                i.setAttribute('autocomplete','off');
	        }
	        
	        /* set input content via POST, GET, given data or existing value */
	        /* this looks weird because it is for maintaining bc */
	        var url;
	        var type;
	                
	        if (settings.getload) {	         
				url = settings.getload;
	            type = 'GET';
	        } else if (settings.postload) {	
	            url = settings.postload;
	            type = 'POST';      
	        }
	
	        if (url) {
	            var data = {};
	            data[settings.id] = self.id;
	            jQuery.ajax({
	               type : type,
	               url  : url,
	               data : data,
	               success: function(str) {
	                  i.value = str;
	               }
	            });
	        } else if (settings.data) {
	            i.value = settings.data;
	        } else { 
	            i.value = self.revert;
	        }
	
	        i.name  = settings.name;
	        f.appendChild(i);
	
	        if (settings.submit) {
	            var b = document.createElement('input');
	            b.type = 'submit';
	            b.value = settings.submit;
	            f.appendChild(b);
	        }
	
	        if (settings.cancel) {
	            var b = document.createElement('input');
	            b.type = 'button';
	            b.value = settings.cancel;
	            f.appendChild(b);
	        }
	
	        /* add created form to self */
	        self.appendChild(f);
	
	        i.focus();
	 
	        /* discard changes if pressing esc */
	        jQuery(i).keydown(function(e) {
	            if (e.keyCode == 27) {
	                e.preventDefault();
	                reset();
	            }
	        });
	
	        /* discard, submit or nothing with changes when clicking outside */
	        /* do nothing is usable when navigating with tab */
	        var t;
	        if ('cancel' == settings.onblur) {
	            jQuery(i).blur(function(e) {
	                t = setTimeout(reset, 500)
	            });
	        /* TODO: does not currently work */
	        } else if ('submit' == settings.onblur) {
            jQuery(i).blur(function(e) {
                jQuery(f).submit();
            });
	        } else {
	            jQuery(i).blur(function(e) {
	              /* TODO: maybe something here */
	            });
	        }
	
	        jQuery(f).submit(function(e) {
	
	            if (t) { 
	                clearTimeout(t);
	            }
	
	            /* do no submit */
	            e.preventDefault(); 
	
	            /* add edited content and id of edited element to POST */           
	            var p = {};
	            p[i.name] = jQuery(i).val();
	            p[settings.id] = self.id;
				p[settings.rowID] = row; // provide updated row and column
				p[settings.colID] = col; 
				
	
	            /* show the saving indicator */
	            if (settings.indicator)
					jQuery(self).html(settings.indicator);
				else 
					jQuery(self).html("Saving...");
					     
	            jQuery.post(settings.url, p, function(str) {
	                self.innerHTML = str;
	                self.editing = false;
	            });
	            return false;
	        });
	
	        function reset() {
	            self.innerHTML = self.revert;
	            self.editing   = false;
	        }
				
		});
	});		
	return(this);
}

